#ifndef __RING_QUEUE_
#define __RING_QUEUE_

#include <iostream>
#include <vector>
#include "sem_num.hpp"

#define _default_queue_size 10

template <class T>
class RingQueue
{
public: 
   RingQueue(const int Num = _default_queue_size)
      :ringqueue(Num)
      ,_num(Num)
      ,c_step(0)
      ,p_step(0)
      ,space_sem(_default_queue_size)
      ,data_sem(0)
   {
      pthread_mutex_init(&c_lock, nullptr);
      pthread_mutex_init(&p_lock, nullptr);
   }

   ~RingQueue()
   {
      pthread_mutex_destroy(&c_lock);
      pthread_mutex_destroy(&p_lock);
   }

   void push(const T& data)
   {
         //生产者循环输入资源
         space_sem.P();  // 空间资源--
         pthread_mutex_lock(&p_lock);
         ringqueue[p_step++] = data;
         p_step %= _num;
         pthread_mutex_unlock(&p_lock);
         data_sem.V();  // 信号量资源++
   }

   void pop(T& data)
   {
         //消费者循环获取数据
         data_sem.P();
         pthread_mutex_lock(&c_lock);
         data = ringqueue[c_step++];
         c_step %= _num;
         pthread_mutex_unlock(&c_lock);
         space_sem.V();
   }

private: 
    std::vector<T> ringqueue;
    int _num;    // 记录圆环长度
    int c_step;  //消费者所在下标值
    int p_step;  //生产者所在下标值
    SemNum space_sem;  // 空间资源信号量，给生产者
    SemNum data_sem;   // 数据资源信号量, 给消费者
    pthread_mutex_t c_lock;  // 消费者锁
    pthread_mutex_t p_lock;  // 生产者锁
};

#endif


